# frozen_string_literal: true

class RuleCondition < ApplicationRecord
  include Ordinalable

  module RvalueType
    extend ConstantEnum

    VALUE = 'value'
    VARIABLE = 'variable'
    FORMULA = 'formula'
  end

  belongs_to :general_rule, class_name: 'RuleEntity::GeneralRule::Condition'

  before_create :auto_set_rvalue_type

  validates :rvalue_type, inclusion: { in: RvalueType.values }, allow_blank: true

  def deep_clone_to_draft
    self.class.create! slice(:ordinal, :lvalue, :operator, :rvalue)
  end

  def validate(variable_names)
    raise "rule_conditions 缺少输入参数: #{lvalue}" unless variable_names.include?(lvalue)

    case rvalue_type
    when RvalueType::VALUE
      logger.debug { 'TODO' }
    when RvalueType::VARIABLE
      raise "rule_conditions 缺少输入参数: #{rvalue}" unless variable_names.include?(rvalue)
    when RvalueType::FORMULA
      logger.debug { 'TODO, parse AST.' }
    end
  end

  def fire(params, variable_types)
    actual_value = params[lvalue] || params[lvalue.to_sym]
    expected_value = calc_rvalue(params, variable_types)
    case operator
    when '='
      actual_value.eql? expected_value
    else
      raise 'Unsupported operator.'
    end
  rescue StandardError => e
    logger.error e
    false
  end

  private

  def calc_rvalue(params, variable_types)
    case rvalue_type
    when RvalueType::VALUE
      rvalue
      variable_types[lvalue].parse(rvalue)
    when RvalueType::VARIABLE
      params[rvalue] || params[rvalue.to_sym]
    when RvalueType::FORMULA
      ScriptSandbox.eval_script(rvalue, params)
    end
  end

  def auto_set_rvalue_type
    self.rvalue_type ||= RvalueType::VALUE
  end
end
